from __future__ import absolute_import, division

from core import *

from .controllers import *
from .solids import *
from .widgets import *


class PandaGameDialog(PandaDialog, GameDialog):
    view    = Attribute(initiable = False)
    terrain = Attribute(initiable = False)
    
    known = DictAttribute(initiable = False)
    
    start = Attribute(initiable = False, writable = True)
    
    def setup_primitives(self):
        self.assign_primitive(self.build_panel,     PandaBuildingsPanel)
        self.assign_primitive(self.date_bar,        PandaDateBar)
        self.assign_primitive(self.name_bar,        PandaCityNameBar)
        self.assign_primitive(self.state_bar,       PandaCityStateBar)
        self.assign_primitive(self.build_bar,       PandaBuildBar)
        self.assign_primitive(self.selected_panel,  PandaSelectedPanel)
    
    def setup_alignments(self):
        self.date_bar       .align_at(self.screen.alignment_point.top_left      .displacement(-3, -2))
        self.name_bar       .align_at(self.screen.alignment_point.top           .displacement( 0, -2))
        self.state_bar      .align_at(self.screen.alignment_point.top_right     .displacement( 3, -2))
        self.build_bar      .align_at(self.screen.alignment_point.top_right     .displacement( 3, 31))
        self.build_panel    .align_at(self.screen.alignment_point.top_right     .displacement( 3, 29))
        self.selected_panel .align_at(self.screen.alignment_point.bottom_left   .displacement(-3,  1))
        
    def setup_dialog(self):    
        self.view    = ViewController(self, self.scenario.size, self.primitive.mouse, self.primitive.show_base.render, self.primitive.show_base.cam.node().getDisplayRegion(0), self.primitive.model)
        self.terrain = TerrainPlane(self.primitive.show_base.render, self.scenario.size, self.scenario.geography, self.primitive.resources, self.primitive.show_base.camera, self.scenario.map)
        
        self.view.center_camera_on_map()
        
        self.primitive.show_base.accept('wheel_up',   self.view.zoom_in)
        self.primitive.show_base.accept('wheel_down', self.view.zoom_out)
        self.primitive.show_base.accept('mouse3',     self.on_right_click)
        self.primitive.show_base.accept('mouse1-up',  self.on_release)

    def on_update_renderer(self):
        self.terrain.update()
        self.view   .update()
        
        self.update_objects(self.city.virtual,   PlaceholderBuilding, virtual = True)
        self.update_objects(self.city.buildings, PlaceholderBuilding)
        self.update_objects(self.city.people,    PlaceholderPerson)
        self.update_objects([tile for tile in self.city.map.tiles if tile.terrain.is_a(Forest)], PlaceholderTree)
    
    def update_objects(self, current, type, **kwds):
        key = tuple([type] + sorted(list(kwds.items())))
        
        if not key in self._known:
            self._known[key] = {}
        
        old = set(self.known[key].keys())
        new = set(current)
        
        for object in new - old:
            self._known[key][object] = type(self.primitive.resources, self.primitive.show_base.render, str(id(object)), object, **kwds)
        
        for object in old - new:
            self._known[key][object].remove()
            
            del self._known[key][object]
        
        for object in current:
            self._known[key][object].update()
    
    def on_click(self):
        if not self.has_selected_tile:
            return
        
        if self.start is None:
            self.start = self.view.picker.vector
        
    def on_release(self):
        self.on_map_clicked(self.selected_tile)
        
        self.start = None
    
    def on_right_click(self):
        if self.start is not None:
            self.start = None
        else:
            self.on_cancel()
    
    @property
    def start_position(self):
        if self.start is not None:
            return Position(self.start[0],
                            self.scenario.height - self.start[1]).integral
        else:
            return None
    
    @property
    def selected_position(self):
        if self.has_selected_tile:
            return Position(self.view.picker.point[0],
                            self.scenario.height - self.view.picker.point[1]).integral
        else:
            return None
    
    @property
    def has_selected_tile(self):
        return (self.view.picker.point is not None)
    
    @property
    def has_selected_area(self):
        return (self.start_position is not None and self.has_selected_tile and self.start_position != self.selected_position)
    
    def center_view_on(self, position):
        self.view.center_camera_on(position)
